package 设计模式;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author shy_black
 * @date 2019/3/14 20:12
 * @Description:
 * Lock面向使用者，定义了使用者与锁交互的接口，影藏了实现细节
 * AQS面向锁的实现者，简化了锁的实现方式，屏蔽同步状态的管理，线程排队，线程等待与唤醒等底层操作
 */
public class 模板模式_MyLock implements Lock {
    private Sync sync = new Sync();
    //锁的实际实现者
    static class Sync extends AbstractQueuedSynchronizer {
        //模板方法在AQS中的Acquire方法

        //        public final void acquire(int arg) {
//            if (!tryAcquire(arg) &&
//                    acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//                selfInterrupt();
//        }
        @Override
        //规定同步状态为1
        protected boolean tryAcquire(int arg) {
            if (arg != 1) {
                throw new RuntimeException("arg != 1...");
            }
            if (compareAndSetState(0, 1)) {
                //当前线程成功获取到锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;

        }

        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0)
                throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }

    //-------------------------Lock接口方法------------------------
    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);

    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, time);
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

class MyThread implements Runnable {
    Lock lock = new 模板模式_MyLock();

    @Override
    public void run() {
        try {
            lock.lock();
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}


class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(myThread);
            thread.start();
        }
    }
}
